#include <iostream>
using namespace std;

class Person
{
public:
  // 构造函数
  // 无参构造（默认构造）
  // 普通构造函数
  Person()
  {
    cout << "Person 构造函数调用" << endl;
  }
  // 有参构造
  // 普通构造函数
  Person(int a)
  {
    age = a;
    cout << "Person 构造函数调用" << a << endl;
  }

  // 拷贝构造函数
  Person(const Person &p)
  {
    // 将传入的人身上所有属性，拷贝到自己身上
    age = p.age;
    cout << "Person 拷贝构造函数调用" << endl;
  }

  ~Person()
  {
    cout << "Person 析构函数调用" << endl;
  }

  int age; // 年龄
};

// 调用
void test01()
{
  // 1. 括号法
  Person p1;     // 默认构造函数的调用
  Person p2(10); // 有参构造函数
  Person p3(p2); // 拷贝构造函数调用

  // 注意事项
  // 调用默认构造函数时，不要加()
  // 因为增加()，编译器会认为是一个函数的声明，不会认为在创建对象
  // Person p1();
  // void func();

  cout << "p1的年龄：" << p1.age << endl;
  cout << "p2的年龄：" << p2.age << endl;
  cout << "p3的年龄：" << p3.age << endl;
  // 2. 显示法
  Person p4 = Person(20); // 有参构造
  Person p5 = Person(p4); // 拷贝构造

  Person(30); // 匿名对象，特点：当前行执行结束后，系统会立即回收掉匿名对象

  // 注意事项2
  // 不要利用拷贝构造函数，初始化匿名对象 编译器会认为 Person(p5) === Person p5; 对象声明
  // Person(p5);

  cout << "aaaaa" << endl;
  // 3. 隐式转换法
  Person p6 = 40; // 相当于写了 Person p6 = Person(10)
  Person p7 = p6;
}

int main(int argc, char const *argv[])
{
  test01();

  return 0;
}